/**
 * 通过crypto-js实现 加解密工具
 * AES、HASH(MD5、SHA256)、base64
 * @author: 阿坤
 */
const CryptoJS = require("crypto-js");
const Crypto = require("crypto");

const KP = {
    key: '90268d3dc304f5f3', 
    iv: 'b894f52b46104ab2'
};

// 加密函数
function encrypt(text) {
    const cipher = Crypto.createCipheriv('aes-128-cbc', KP.key,KP.iv);
    let encrypted = cipher.update(text, 'utf8', 'hex');
    encrypted += cipher.final('hex');
    return encrypted;
}
// 解密函数
function decrypt(encryptedText) {
    const decipher = Crypto.createDecipheriv('aes-128-cbc',KP.key,KP.iv);
    let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
    decrypted += decipher.final('utf8');
    return decrypted;
}

// AES 对称秘钥加密
const aes = {
    /** 加密 */
    en: (value) => encrypt(value),
    /** 解密 */
    de: (value) => decrypt(value)
};
// BASE64
const base64 = {
    en: (value) => CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(value)),
    de: (value) => CryptoJS.enc.Base64.parse(value).toString(CryptoJS.enc.Utf8)
};
const md5 = (value) => {
    return CryptoJS.MD5(value).toString();
};
// SHA256
const sha256 = (data) => {
    return CryptoJS.SHA256(data).toString();
};
// RSA 签名
const rsa = {
    // 私钥签名
    sign: (data, privateKey) => {
        let sign = Crypto.createSign('RSA-SHA256');
        sign.update(data);
        return sign.sign({ key: privateKey }, 'base64');
    },
    // 公钥验签
    verify: (data, signature, publicKey) => {
        let verify = Crypto.createVerify('RSA-SHA256');
        verify.update(data);
        return verify.verify({ key: publicKey }, signature, 'base64');
    }
};

/**
 * 生成签名
 * @param {Object} params 待签名数据
 * @param {String} key 秘钥
 * @param {Array}  excludes 排除的参数
 * @returns {String} 签名
 */
const setSign = (params, key = '', excludes = ['sign','sign_type'])=>{
    const sortedParams = Object.keys(params)
        .filter(key => !excludes.includes(key) && params[key])
        .sort((a,b)=>a.localeCompare(b))
        .map(key => `${key}=${params[key]}`)
        .join('&');
    const toBeHashed = `${sortedParams}${key}`;
    const hash =  Crypto.createHash('md5').update(toBeHashed).digest("hex");
    return hash.toLowerCase();
}

module.exports = {
    aes,
    rsa,
    md5,
    sha256,
    base64,
    setSign
}
